package com.yunhe.history.controller.data;

import com.yunhe.history.domain.data.ChargeAndDischargeCurve;
import com.yunhe.common.exception.ArgumentErrorException;
import com.yunhe.common.exception.ObjectNotFoundException;
import com.yunhe.common.model.DomainList;
import com.yunhe.common.model.PageParam;
import com.yunhe.common.model.ResultObject;
import com.yunhe.common.model.data.Measurement;
import com.yunhe.common.model.data.MeasurementDpuDTO;
import com.yunhe.common.model.data.MeasurementReqDTO;
import com.yunhe.history.service.data.MeasurementService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import com.yunhe.common.util.CollectionUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.web.bind.annotation.*;

import java.util.*;

/**
 * 量测Controller
 * @author liuronglei
 */
@Api(value = "measurement",description = "量测维护", tags = {"Data_Measurement"})
@RestController
@EnableAsync
@RequestMapping("/measurements")
public class MeasurementController {

    private static final Logger logger = LoggerFactory.getLogger(MeasurementController.class);
    @Autowired
    @Qualifier("influxDBMeasurementServiceImpl")
    private MeasurementService measurementService;

    /**
     * 新增量测
     * @param measurement 量测对象
     * @param frequency 时间频率
     */
    @ApiOperation("新增量测")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "frequency", value = "时间频率", dataType = "string", paramType = "query")
    })
    @RequestMapping(method = RequestMethod.POST)
    public ResponseEntity<ResultObject> post(@RequestBody Measurement measurement,
                                             @RequestParam("frequency") Optional<String> frequency)
            throws ArgumentErrorException {
        Measurement newMeasurement = measurementService.createMeasurement(measurement, frequency.orElse(null));
        return new ResponseEntity<>(new ResultObject<>(newMeasurement), HttpStatus.OK);
    }

    /**
     * 批量新增量测（异步执行）
     * 为了避免处理时间过长，导致返回报错，故采用异步执行
     * @param domainList 量测对象列表
     * @param frequency 时间频率
     */
    @ApiOperation("批量新增量测（异步执行）")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "frequency", value = "时间频率", dataType = "string", paramType = "query")
    })
    @RequestMapping(value = "/batch", method = RequestMethod.POST)
    public ResponseEntity<ResultObject> post(@RequestBody DomainList<Measurement> domainList,
                                             @RequestParam("frequency") Optional<String> frequency)
            throws ArgumentErrorException {
        List<Measurement> measurementList = domainList.getList();
        measurementService.createMeasurementAsync(measurementList, frequency.orElse(null));
        return new ResponseEntity<>(new ResultObject<>(null), HttpStatus.OK);
    }

    @ApiOperation("批量新增量测数据（DPU上传数据，异步执行）")
    @RequestMapping(value = "/batch/dpu", method = RequestMethod.POST)
    public ResponseEntity<ResultObject> createFromDpu(@RequestBody List<List<MeasurementDpuDTO>> measurements)
            throws ArgumentErrorException {
        measurementService.createMeasurementFromDpuAsync(measurements);
        return new ResponseEntity<>(new ResultObject<>(null), HttpStatus.OK);
    }

    /**
     * 根据点号删除量测
     * @param pointNumber 点号
     */
    @ApiOperation("根据点号删除量测")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "pointNumber", value = "点号", required = true, dataType = "long", paramType = "path")
    })
    @RequestMapping(value = "/{pointNumber}", method = RequestMethod.DELETE)
    public ResponseEntity<ResultObject> delete(@PathVariable("pointNumber") Long pointNumber,
                                               @RequestParam("frequency") Optional<String> frequency) {
        Long result = measurementService.deleteByPointNumber(pointNumber, frequency.orElse(null));
        return new ResponseEntity<>(new ResultObject<>(result), HttpStatus.OK);
    }

    /**
     * 根据条件获得量测列表
     * @param pointNumber 点号
     * @param dtime 时间范围
     * @param frequency 时间频率
     * @param flag 标记
     */
    @ApiOperation("根据条件获得量测列表")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "pointNumber", value = "点号", dataType = "long", paramType = "query", required = true),
            @ApiImplicitParam(name = "dtime", value = "时间范围，如“2017-12-06 00:00:00,2017-12-06 23:45:00”", required = true, dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "frequency", value = "时间频率", dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "flag", value = "标记", dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "fill", value = "是否填充，默认true", dataType = "boolean", paramType = "query")
    })
    @RequestMapping(method = RequestMethod.GET)
    public ResponseEntity<ResultObject> search(@RequestParam("pointNumber") Long pointNumber,
                                               @RequestParam("dtime") List<String> dtime,
                                               @RequestParam("frequency") Optional<String> frequency,
                                               @RequestParam("flag") Optional<Integer> flag,
                                               @RequestParam("fill") Optional<Boolean> fill,
                                               @ModelAttribute PageParam pageParam)
            throws ArgumentErrorException {
        Iterable<Measurement> results = null;
        if (pointNumber != null) {
            results = measurementService.findMeasurements(pointNumber, dtime,
                    frequency.orElse(null), flag.orElse(null), fill.orElse(null), pageParam);
        }
        return new ResponseEntity<>(new ResultObject<>(results), HttpStatus.OK);
    }

    @ApiOperation("根据条件获得量测列表")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "pointNumbers", value = "点号", dataType = "long", paramType = "query", required = true),
            @ApiImplicitParam(name = "dtime", value = "时间范围，如“2017-12-06 00:00:00,2017-12-06 23:45:00”", required = true, dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "frequency", value = "时间频率", dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "flag", value = "标记", dataType = "string", paramType = "query")
    })
    @RequestMapping(value = "/page", method = RequestMethod.GET)
    public ResponseEntity<ResultObject> search(@RequestParam("pointNumbers") List<Long> pointNumbers,
                                               @RequestParam("dtime") List<String> dtime,
                                               @RequestParam("frequency") Optional<String> frequency,
                                               @RequestParam("flag") Optional<Integer> flag,
                                               @ModelAttribute PageParam pageParam)
            throws ArgumentErrorException {
        Iterable<Measurement> results = measurementService.findMeasurements(pointNumbers, dtime,
                frequency.orElse(null), flag.orElse(null), pageParam);
        return new ResponseEntity<>(new ResultObject<>(results), HttpStatus.OK);
    }

    @ApiOperation("根据条件删除量测列表")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "pointNumber", value = "点号", dataType = "long", paramType = "query"),
            @ApiImplicitParam(name = "frequency", value = "时间频率", dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "flag", value = "标记", dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "dtime", value = "时间范围，如“2017-12-06 00:00:00,2017-12-06 23:45:00”", required = true, dataType = "string", paramType = "query")
    })
    @RequestMapping(method = RequestMethod.DELETE)
    public ResponseEntity<ResultObject> delete(@RequestParam("pointNumber") Long pointNumber,
                                               @RequestParam("dtime") List<String> dtime,
                                               @RequestParam("frequency") Optional<String> frequency,
                                               @RequestParam("flag") Optional<Integer> flag,
                                               @ModelAttribute PageParam pageParam)
            throws ArgumentErrorException {
        if (pointNumber != null) {
            measurementService.deleteMeasurements(pointNumber, dtime,
                    frequency.orElse(null), flag.orElse(null), pageParam);
        }
        return new ResponseEntity<>(new ResultObject<>(null), HttpStatus.OK);
    }

    @ApiOperation("根据点号(功率)获得指定时间段的充电或者放电积分值")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "pointNumber", value = "点号", required = true, dataType = "long", paramType = "query"),
            @ApiImplicitParam(name = "dtime", value = "日期", required = true, dataType = "string", paramType = "query"),
    })
    @RequestMapping(value = "/calcIntegral", method = RequestMethod.GET)
    public ResponseEntity<ResultObject> calcByIntegral(@RequestParam("pointNumber") Long pointNumber,
                                                       @RequestParam("dtime") List<String> dates)
            throws ArgumentErrorException {
        ChargeAndDischargeCurve result = measurementService.calcByIntegral(pointNumber, dates);
        return new ResponseEntity<>(new ResultObject<>(result), HttpStatus.OK);
    }

    @ApiOperation("根据时间范围获得量测值")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "pointNumber", value = "点号", required = true, dataType = "long", paramType = "query"),
            @ApiImplicitParam(name = "dtime", value = "时间范围，如“2017-12-06 00:00:00,2017-12-06 23:45:00”", required = true, dataType = "string", paramType = "query")
    })
    @RequestMapping(value = "/byTimeRange", method = RequestMethod.GET)
    public ResponseEntity<ResultObject> findMeasurementsEitherEnd(@RequestParam("pointNumber") Long pointNumber,
                                                                  @RequestParam("dtime") List<String> dtime,
                                                                  @RequestParam("frequency") Optional<String> frequency,
                                                                  @RequestParam("flag") Optional<Integer> flag)
            throws ArgumentErrorException {
        Iterable<Measurement> results = measurementService.findMeasurementsEitherEnd(pointNumber, dtime,
                frequency.orElse(null), flag.orElse(null));
        return new ResponseEntity<>(new ResultObject<>(results), HttpStatus.OK);
    }

    @ApiOperation("根据时间范围获得量测值")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "pointNumber", value = "点号", required = true, dataType = "long", paramType = "query"),
            @ApiImplicitParam(name = "dtime", value = "时间范围，如“2017-12-06 00:00:00,2017-12-06 23:45:00”", required = true, dataType = "string", paramType = "query")
    })
    @RequestMapping(value = "/byTimeRange/batch", method = RequestMethod.GET)
    public ResponseEntity<ResultObject> findMeasurementsEitherEnd(@RequestParam("pointNumber") List<Long> pointNumber,
                                                                  @RequestParam("dtime") List<String> dtime,
                                                                  @RequestParam("frequency") Optional<String> frequency,
                                                                  @RequestParam("flag") Optional<Integer> flag)
            throws ArgumentErrorException {
        List<List<Measurement>> results = measurementService.findMeasurementsEitherEnd(pointNumber, dtime,
                frequency.orElse(null), flag.orElse(null));
        return new ResponseEntity<>(new ResultObject<>(results), HttpStatus.OK);
    }

    @ApiOperation("根据点号获取最新量测对象")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "pointNumber", value = "点号", required = true, dataType = "long", paramType = "query")
    })
    @RequestMapping(value = "/last", method = RequestMethod.GET)
    public ResponseEntity<ResultObject> findMeasurementsLast(@RequestParam("pointNumber") Long pointNumber) {
        Measurement result = measurementService.findMeasurementsLast(pointNumber);
        return new ResponseEntity<>(new ResultObject<>(result), HttpStatus.OK);
    }

    @ApiOperation("根据点号批量获取最新量测对象")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "pointNumber", value = "点号，多个点号以逗号间隔", required = true, dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "frequency", value = "时间频率", dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "flag", value = "标记", dataType = "string", paramType = "query")
    })
    @RequestMapping(value = "/last/batch", method = RequestMethod.GET)
    public ResponseEntity<ResultObject> findMeasurementsLastBatch(@RequestParam("pointNumber") List<Long> pointNumbers,
                                                                  @RequestParam("frequency") Optional<String> frequency,
                                                                  @RequestParam("flag") Optional<Integer> flag,
                                                                  @RequestParam("endTime") Optional<String> endTime) {
        Map<Long, Measurement> result = measurementService.findMeasurementsLastBatch(pointNumbers,
                frequency.orElse(null), flag.orElse(null), endTime.orElse(null));
        return new ResponseEntity<>(new ResultObject<>(result), HttpStatus.OK);
    }

    @ApiOperation("根据点号批量获取最新量测值_POST模式")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "frequency", value = "时间频率", dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "flag", value = "标记", dataType = "string", paramType = "query")
    })
    @RequestMapping(value = "/last/batch", method = RequestMethod.POST)
    public ResponseEntity<ResultObject> findMeasurementsLastBatch(@RequestBody MeasurementReqDTO measurementReqDTO,
                                                                  @RequestParam("frequency") Optional<String> frequency,
                                                                  @RequestParam("flag") Optional<Integer> flag,
                                                                  @RequestParam("endTime") Optional<String> endTime) {
        if (measurementReqDTO == null || CollectionUtil.isEmpty(measurementReqDTO.getPointNumber())) {
            return new ResponseEntity<>(new ResultObject<>(null), HttpStatus.OK);
        }
        Map<Long, Measurement> result = measurementService.findMeasurementsLastBatch(measurementReqDTO.getPointNumber(),
                frequency.orElse(null), flag.orElse(null), endTime.orElse(null));
        return new ResponseEntity<>(new ResultObject<>(result), HttpStatus.OK);
    }

//    @ApiOperation("获取某一时刻没有量测值的点号")
//    @ApiImplicitParams({
//            @ApiImplicitParam(name = "dtime", value = "时间", required = true, dataType = "string", paramType = "query")
//    })
//    @RequestMapping(value = "/pnWithoutValue", method = RequestMethod.GET)
//    public ResponseEntity<ResultObject> getPnWithoutValue(@RequestParam("dtime") String dtime) {
//        List<String> results = measurementService.findPnWithoutValue(dtime);
//        return new ResponseEntity<>(new ResultObject<>(results), HttpStatus.OK);
//    }

    @ApiOperation("根据点号获得点号与最后一次值不同的前一次的值")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "pointNumber", value = "点号", required = true, dataType = "long", paramType = "query")
    })
    @RequestMapping(value = "/preValue", method = RequestMethod.GET)
    public ResponseEntity<ResultObject> getPreValue(@RequestParam("pointNumber") Long pointNumber) {
        Double result = measurementService.getPreValue(pointNumber);
        return new ResponseEntity<>(new ResultObject<>(result), HttpStatus.OK);
    }

    @ApiOperation("获取点号在给定时间之前的最新值")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "pointNumber", value = "点号", required = true, dataType = "long", paramType = "query"),
            @ApiImplicitParam(name = "dtime", value = "时间", required = true, dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "frequency", value = "时间频率", dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "flag", value = "标记", dataType = "string", paramType = "query")
    })
    @RequestMapping(value = "/preValue/byTime", method = RequestMethod.GET)
    public ResponseEntity<ResultObject> getPreValue(@RequestParam("pointNumber") Long pointNumber,
                                                    @RequestParam("dtime") String dtime,
                                                    @RequestParam("frequency") Optional<String> frequency,
                                                    @RequestParam("flag") Optional<Integer> flag) {
        Double result = measurementService.getPreValue(pointNumber, dtime,
                frequency.orElse(null), flag.orElse(null));
        return new ResponseEntity<>(new ResultObject<>(result), HttpStatus.OK);
    }

    @ApiOperation("获取点号在给定时间之前的最新值")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "pointNumbers", value = "点号", required = true, dataType = "long", paramType = "query"),
            @ApiImplicitParam(name = "rtime", value = "时间戳", required = true, dataType = "long", paramType = "query"),
            @ApiImplicitParam(name = "frequency", value = "时间频率", dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "flag", value = "标记", dataType = "string", paramType = "query")
    })
    @RequestMapping(value = "/preValues/byTime", method = RequestMethod.GET)
    public ResponseEntity<ResultObject> getPreValues(@RequestParam("pointNumbers") List<Long> pointNumbers,
                                                     @RequestParam("rtime") Long rtime,
                                                     @RequestParam("frequency") Optional<String> frequency,
                                                     @RequestParam("flag") Optional<Integer> flag) {
        Map<Long, Double> result = measurementService.getPreValues(pointNumbers, rtime,
                frequency.orElse(null), flag.orElse(null));
        return new ResponseEntity<>(new ResultObject<>(result), HttpStatus.OK);
    }

    @ApiOperation("获取点号在给定时间之后的最新量测对象")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "pointNumber", value = "点号", required = true, dataType = "long", paramType = "query"),
            @ApiImplicitParam(name = "dtime", value = "时间", required = true, dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "frequency", value = "时间频率", dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "flag", value = "标记", dataType = "string", paramType = "query")
    })
    @RequestMapping(value = "/nextValue/byTime", method = RequestMethod.GET)
    public ResponseEntity<ResultObject> getNextValue(@RequestParam("pointNumber") Long pointNumber,
                                                     @RequestParam("dtime") String dtime,
                                                     @RequestParam("frequency") Optional<String> frequency,
                                                     @RequestParam("flag") Optional<Integer> flag) {
        Measurement result = measurementService.getNextMeasurement(pointNumber, dtime,
                frequency.orElse(null), flag.orElse(null));
        return new ResponseEntity<>(new ResultObject<>(result), HttpStatus.OK);
    }

    /**
     * 根据条件获得量测列表
     * @param pointNumbers 点号
     * @param dtime 时间范围
     * @param frequency 时间频率
     * @param flag 标记
     * @param fill 是否填充，默认true
     */
    @ApiOperation("根据条件获得量测列表")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "pointNumbers", value = "点号", required = true, dataType = "long", paramType = "query"),
            @ApiImplicitParam(name = "dtime", value = "时间范围，如“2017-12-06 00:00:00,2017-12-06 23:45:00”", required = true, dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "frequency", value = "时间频率", dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "flag", value = "标记", dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "fill", value = "是否填充，默认true", dataType = "boolean", paramType = "query"),
            @ApiImplicitParam(name = "queryAllAfterDtime", value = "是否查询给定时间之后的所有数据，默认false", dataType = "boolean", paramType = "query")
    })
    @RequestMapping(value = "/batch" ,method = RequestMethod.GET)
    public ResponseEntity<ResultObject> search(@RequestParam("pointNumbers") List<Long> pointNumbers,
                                               @RequestParam("dtime") List<String> dtime,
                                               @RequestParam("frequency") Optional<String> frequency,
                                               @RequestParam("flag") Optional<Integer> flag,
                                               @RequestParam("fill") Optional<Boolean> fill,
                                               @RequestParam("queryAllAfterDtime") Optional<Boolean> queryAllAfterDtime)
            throws ArgumentErrorException {
        Map<Long, List<Measurement>> measures = measurementService.getMeasurementMap(pointNumbers, dtime,
                frequency.orElse(null), flag.orElse(null), fill.orElse(null), queryAllAfterDtime.orElse(false));
        List<List<Measurement>> results = new LinkedList<>();
        for (Long pointNumber : pointNumbers) {
            List<Measurement> measurements = measures.get(pointNumber);
            results.add(measurements == null ? Collections.emptyList() : measurements);
        }
        return new ResponseEntity<>(new ResultObject<>(results), HttpStatus.OK);
    }

    /**
     * 根据条件获得量测列表
     * @param pointNumbers 点号
     * @param dtime 时间范围
     * @param frequency 时间频率
     * @param flag 标记
     * @param fill 是否填充，默认true
     */
    @ApiOperation("根据条件获得量测列表")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "pointNumbers", value = "点号", required = true, dataType = "long", paramType = "query"),
            @ApiImplicitParam(name = "dtime", value = "时间范围，如“2017-12-06 00:00:00,2017-12-06 23:45:00”", required = true, dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "frequency", value = "时间频率", dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "flag", value = "标记", dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "fill", value = "是否填充，默认true", dataType = "boolean", paramType = "query")
    })
    @RequestMapping(value = "/batchWithMap" ,method = RequestMethod.GET)
    public ResponseEntity<ResultObject> searchWithMap(@RequestParam("pointNumbers") List<Long> pointNumbers,
                                                      @RequestParam("dtime") List<String> dtime,
                                                      @RequestParam("frequency") Optional<String> frequency,
                                                      @RequestParam("flag") Optional<Integer> flag,
                                                      @RequestParam("fill") Optional<Boolean> fill)
            throws ArgumentErrorException {
        Map<Long, List<Measurement>> measures = measurementService.getMeasurementMap(pointNumbers, dtime,
                frequency.orElse(null), flag.orElse(null), fill.orElse(null), false);
        return new ResponseEntity<>(new ResultObject<>(measures), HttpStatus.OK);
    }

    /**
     * 根据条件获得量测列表
     * @param measurementReqDTO 点号
     * @param dtime 时间范围
     * @param frequency 时间频率
     * @param flag 标记
     * @param fill 是否填充，默认true
     */
    @ApiOperation("根据条件获得量测列表")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "pointNumbers", value = "点号", required = true, dataType = "long", paramType = "query"),
            @ApiImplicitParam(name = "dtime", value = "时间范围，如“2017-12-06 00:00:00,2017-12-06 23:45:00”", required = true, dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "frequency", value = "时间频率", dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "flag", value = "标记", dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "fill", value = "是否填充，默认true", dataType = "boolean", paramType = "query")
    })
    @RequestMapping(value = "/batchWithMap" ,method = RequestMethod.POST)
    public ResponseEntity<ResultObject> searchWithMapByPost(@RequestBody MeasurementReqDTO measurementReqDTO,
                                                            @RequestParam("dtime") List<String> dtime,
                                                            @RequestParam("frequency") Optional<String> frequency,
                                                            @RequestParam("flag") Optional<Integer> flag,
                                                            @RequestParam("fill") Optional<Boolean> fill)
            throws ArgumentErrorException {
        Map<Long, List<Measurement>> measurements = measurementService.getMeasurementMapByShard(measurementReqDTO.getPointNumbers(), dtime,
                frequency.orElse(null), flag.orElse(null), fill.orElse(null));
        return new ResponseEntity<>(new ResultObject<>(measurements), HttpStatus.OK);
    }

    @ApiOperation("根据条件获得量测列表（分片方式）")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "dtime", value = "时间范围，如“2017-12-06 00:00:00,2017-12-06 23:45:00”", required = true, dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "frequency", value = "采样频率", dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "flag", value = "标记", dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "fill", value = "是否填充，默认true", dataType = "boolean", paramType = "query")
    })
    @RequestMapping(value = "/batchGet" ,method = RequestMethod.POST)
    public ResponseEntity<ResultObject> batchGet(@RequestBody MeasurementReqDTO measurementReqDTO,
                                                 @RequestParam("dtime") List<String> dtime,
                                                 @RequestParam("frequency") Optional<String> frequency,
                                                 @RequestParam("flag") Optional<Integer> flag,
                                                 @RequestParam("fill") Optional<Boolean> fill)
            throws ObjectNotFoundException, ArgumentErrorException {
        List<Long> pointNumbers = new ArrayList<>();
        if (measurementReqDTO.getPointNumbers() != null) {
            pointNumbers.addAll(measurementReqDTO.getPointNumbers());
        } else if (measurementReqDTO.getPointNumberStrs() != null) {
            List<String> list = measurementReqDTO.getPointNumberStrs();
            for (String s : list) {
                pointNumbers.add(Long.parseLong(s));
            }
        } else {
            throw new ArgumentErrorException("查询点号不能为空");
        }
        Map<Long, List<Measurement>> measurements = measurementService.getMeasurementMapByShard(pointNumbers, dtime,
                frequency.orElse(null), flag.orElse(null), fill.orElse(null));
        List<List<Measurement>> result = new ArrayList<>();
        pointNumbers.forEach(pid -> {
            List<Measurement> list = measurements.get(pid);
            result.add(list != null ? list : new ArrayList<>());
        });
        return new ResponseEntity<>(new ResultObject<>(result), HttpStatus.OK);
    }

//    /**
//     * 根据点号和值获得第一次出现的时间
//     * @param pointNumber 点号
//     * @param value 点号值
//     */
//    @ApiOperation("根据点号和值获得第一次出现的时间")
//    @ApiImplicitParams({
//            @ApiImplicitParam(name = "pointNumber", value = "点号", required = true, dataType = "long", paramType = "query"),
//            @ApiImplicitParam(name = "value", value = "点号值", required = true, dataType = "double", paramType = "query")
//    })
//    @RequestMapping(value = "/firstValueTime" ,method = RequestMethod.GET)
//    public ResponseEntity<ResultObject> findFirstValueTime(@RequestParam("pointNumber") Long pointNumber,
//                                                           @RequestParam("value") Double value)
//            throws ObjectNotFoundException {
//        String result = measurementService.findFirstValueTime(pointNumber, value);
//        return new ResponseEntity<>(new ResultObject<>(result), HttpStatus.OK);
//    }

    /**
     * 根据条件获得一段时间内量测值最大的量测点
     * @param dtime 时间范围
     * @param frequency 时间频率
     * @param flag 标记
     */
    @ApiOperation("根据条件获得一段时间内量测值最大的量测点")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "pointNumbers", value = "点号列表", dataType = "long", paramType = "query", required = true),
            @ApiImplicitParam(name = "dtime", value = "时间范围，如“2017-12-06 00:00:00,2017-12-06 23:45:00”", required = true, dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "frequency", value = "时间频率", dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "flag", value = "标记", dataType = "string", paramType = "query")
    })
    @RequestMapping(value = "/max", method = RequestMethod.POST)
    public ResponseEntity<ResultObject> searchMaxGet(@RequestBody MeasurementReqDTO measurementReqDTO,
                                                     @RequestParam("dtime") List<String> dtime,
                                                     @RequestParam("frequency") Optional<String> frequency,
                                                     @RequestParam("flag") Optional<Integer> flag)
            throws ArgumentErrorException {
        List<Measurement> results = measurementService.getMaxMeasurement(measurementReqDTO.getPointNumbers(), dtime,
                frequency.orElse(null), flag.orElse(null));
        return new ResponseEntity<>(new ResultObject<>(results), HttpStatus.OK);
    }

    @ApiOperation("根据开始时间和结束时间获得最近的量测值（没有对应时间点的数据，取上一个点）")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "pointNumber", value = "点号", required = true, dataType = "long", paramType = "query"),
            @ApiImplicitParam(name = "dtime", value = "时间范围，如“2017-12-06 00:00:00,2017-12-06 23:45:00”", required = true, dataType = "string", paramType = "query")
    })
    @RequestMapping(value = "/byStartAndEndTime/batch", method = RequestMethod.GET)
    public ResponseEntity<ResultObject> findByStartAndEndTime(@RequestParam("pointNumber") List<Long> pointNumbers,
                                                              @RequestParam("dtime") List<String> dtime,
                                                              @RequestParam("frequency") Optional<String> frequency,
                                                              @RequestParam("flag") Optional<Integer> flag) {
        List<List<Measurement>> results = measurementService.findByStartAndEndTime(pointNumbers, dtime, frequency.orElse(null), flag.orElse(null));
        return new ResponseEntity<>(new ResultObject<>(results), HttpStatus.OK);
    }
}